<?php

class FTPClient
{
    private $host;

    private $port;

    private $user;

    private $password;

    private $connectTimeout = 30;

    private $remotePath;

    private $localPath;

    private $conn;

    private static $fileQueue = array();

    public function __construct($host, $port, $user, $password, $localPath, $remotePath = '')
    {
        echo "initializing...", PHP_EOL;
        $this->host = $host;
        $this->port = $port;
        $this->user = $user;
        $this->password = $password;
        $this->remotePath = $remotePath ? DIRECTORY_SEPARATOR . ltrim(rtrim($remotePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR) : $remotePath;
        $this->localPath = rtrim($localPath, DIRECTORY_SEPARATOR);
        echo "initialise complete...", PHP_EOL;
    }

    public function run()
    {
        $this->connect();
        $this->scan($this->localPath);
        $this->transport();
    }

    private function connect()
    {
        echo "connecting to ftp server...", PHP_EOL;
        $this->conn = ftp_connect($this->host, $this->port, $this->connectTimeout) or die("Unable to connect to ftp server!");
        ftp_login($this->conn, $this->user, $this->password) or die("Incorrect authentication!");
        ftp_chdir($this->conn, $this->remotePath);
    }

    private function scan($localPath)
    {
        $dir = scandir($localPath);
        $tmpFileQueue = self::$fileQueue;
        $obj = $this;
        array_walk($dir, function($v, $k) use (&$tmpFileQueue, $localPath, $obj) {
            if (!in_array($v, array('.', '..'))) {
                $tmpFilePath = $localPath . DIRECTORY_SEPARATOR . $v;
                if (is_dir($tmpFilePath)) {
                    $this->scan($tmpFilePath);
                } else {
                    $relativePath = ltrim(str_replace($obj->localPath, '', $localPath), DIRECTORY_SEPARATOR);
                    self::$fileQueue[$relativePath][] = $tmpFilePath;
                }
            }
        });
    }

    private function transport()
    {
        foreach (self::$fileQueue as $dirPath => $files) {
            ftp_chdir($this->conn, $this->remotePath);
            $dirPathArray = explode(DIRECTORY_SEPARATOR, $dirPath);
            foreach ($dirPathArray as $dir) {
                $dir && @ftp_mkdir($this->conn, $dir) && ftp_chdir($this->conn, $dir);
            }
            foreach ($files as $file) {
                echo "uploading $file", PHP_EOL;
                ftp_put($this->conn, basename($file), $file, FTP_BINARY);
            }
        }
        echo "tranfering complete...", PHP_EOL;
    }
}
